home *** CD-ROM | disk | FTP | other *** search
- /*
-
- generic function dispatcher for GCOOPE Version 1.0
- with current instance tracking via the .fext member of objFlag.
-
- by Brian Lee Price
-
- Released as Public Domain July, 1994.
-
- */
-
- #include <stdarg.h>
- #include <stdlib.h>
-
- #define __FUNCTION_DISPATCHER__
-
- #include "gcstruct.h"
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This is the function dispatcher for GCOOPE, note that it actually
- accesses the first parameter of the generic function's parameters.
- The return function address is a function of the parameter func and
- the object type parameter that is the first parm to the actual call.
- */
-
- method g(generic func,...)
- {
- va_list ap;
- objHndl * instObj;
- boolean update=TRUE;
- tag classTag;
- genMethod * gMthd;
- genEntry * gEntry;
- char * objDef;
-
- va_start(ap,func);
- instObj=(objHndl *) ap;
-
- /* check for the explicit call of default via. the object Object */
- if( *((object *) ap)==Object) goto dfltMthd;
-
- /* test for flag class */
- if(*((object *) instObj)<0)
- {
- classTag=SIGNMASK & (instObj->fext);
- update=FALSE;
- }
- else
- {
- if(NULL==(objDef=getObjDef(instObj->tag))) goto err1;
- objDef+=instObj->fext;
- classTag=*((tag *)objDef);
- if(classTag==(tag) Class)
- {
- classTag=instObj->tag;
- update=FALSE;
- }
- }
-
- /* check for class method existance */
- if(NULL==(gMthd = getMthd(func,classTag)))
- {
- dfltMthd:
- va_end(ap);
- if(func < genTable.maxElems && func >= 0)
- {
- gEntry=genTable.listPtr;
- gEntry+=func;
- if(gEntry->defMthd!=(method) NULL)
- {
- return gEntry->defMthd;
- }
- }
- err1: /* any error routes to the default method for the genFunc Err */
- gEntry=genTable.listPtr;
- gEntry+=(tag) Err;
- return gEntry->defMthd;
- }
- /* bypass if flag class or if a class call */
- if(update)
- {
- if(((object)NULL)==
- (*((object *) ap)=steer((object) gMthd->owner,*((object *) ap))))
- goto err1;
- }
- va_end(ap);
- return gMthd->instMethod;
- }
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- the .fext member of structure type objHndl is used to convey the offset
- within the owning instance's memory block of the current instance's
- instance memory. The macro OBJFLAG treats type object items as if
- they were type objFlag.
- This routine will attempt to adjust the .fext field so that the
- class of the current instance will be that of the passed parm class.
- If unsuccessful, NULL (cast as type object) will be returned.
- Programmers Note: the first item in an object definition memory
- area is of type int and is the class tag of the instance. This holds
- true for instances offset within a child instance memory block.
- Also Note: When calling an ancestor class method from within an
- object method, if that ancestor class is not an immediate superClass,
- the steer process can be speed up by steering it manually. This
- technique also works for inherited instance memory masked by another
- inherited instance memory area of the same class located earlier in
- the recursive ancestor search path.
- */
-
- object steer(object class, object instance)
- {
- superEntry * parent;
- char * objPtr;
- classEntry * clsEnt;
- tag coi,x;
- object newInst;
-
- /* validity check */
- if(instance<0 || ((word) instance) > objList.maxElems)
- return (object) NULL;
-
- /* check if class of current instance is the class sought */
-
- if(NULL==(objPtr=getObjDef((tag)instance))) return (object) NULL;
- objPtr+=((objHndl *) &instance)->fext;
- if((coi=*((tag *) objPtr)) == (tag) class) return instance;
-
- /* immediate superClass scan */
-
- if(NULL==(clsEnt=getObjDef(coi))) return (object) NULL;
- (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
- for(x=clsEnt->numSuper;x>0;x--,parent++)
- {
- if(parent->class==(tag) class)
- {
- ((objHndl *) &instance)->fext+=parent->offset;
- return instance;
- }
- }
-
- /* recursive ancestor search */
- (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
- for(x=clsEnt->numSuper;x>0;x--,parent++)
- {
- newInst=instance;
- ((objHndl *) &newInst)->fext+=parent->offset;
- if((object)NULL != (newInst=steer(class, newInst)))
- {
- return newInst;
- }
- }
- return (object) NULL;
- }
-
-
- /*
- AVAILABLE FOR EXTERNEL USE.
-
- Returns a pointer to the instance's memory.
- */
-
- void * getIVptr(object instance)
- {
- char * retVal;
-
- if(NULL==(retVal=getObjDef((tag) instance))) goto end;
- retVal+=((objHndl *) &instance)->fext + sizeof(tag);
- end:
- return retVal;
- }
-
-
- /*
- FOR KERNEL USE ONLY.
-
- This routine initializes an instance created when an owning
- New (top-level class) calls makeInst.
- */
-
- static stat initInst(tag class, tag offset, char * newObj)
- {
- classEntry * clsEnt;
- superEntry * parent;
- tag * ptrA;
- int x;
-
- if((object) NULL==(clsEnt=getObjDef(class))) return FUNCFAIL;
- (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
- ptrA =(tag *) &(newObj[offset]);
- *ptrA=class;
-
- for(x=clsEnt->numSuper; x>0; x--,parent++)
- {
- if(initInst(parent->class,offset+parent->offset, newObj))
- return FUNCFAIL;
- }
- return FUNCOKAY;
- }
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This routine creates or updates/accesses an instance memory area.
- It returns a pointer to the instance variable memory.
- */
-
- void * makeInst(object * instPtr)
- {
- tag class;
- classEntry * clsEnt;
- char * newObj=NULL;
-
- if(((objHndl *) instPtr)->fext) return getIVptr(*instPtr);
-
- class=((objHndl *)instPtr)->tag;
- if(NULL==(clsEnt=getObjDef(class))) goto end;
- newObj=s_calloc(1,clsEnt->totSize);
- *instPtr = (object) NULL;
- ((objHndl *) instPtr)->tag=addObject(newObj,(byte) curProcID);
-
- if(initInst(class, 0, newObj))
- {
- rmvObject(((objHndl *) instPtr)->tag);
- s_free(newObj);
- return NULL;
- }
- ((tag *) newObj)++;
- end:
- return newObj;
- }
-
-
- /*
- AVAILABLE FOR EXTERNAL USE.
-
- This routine returns a pointer to the class variable area
- accessible by all members of the class.
- */
-
- void * getCVptr(object class)
- {
- classEntry * clsEnt;
-
- if(NULL==(clsEnt=getObjDef((tag) class))) return NULL;
- return clsEnt->cVars;
- }
-
-
-
- /*
- This routine simply returns the passed instance
-
- */
-
- #pragma warn -par
- object bounceBack(object instance,...)
- {
- return instance;
- }
- #pragma warn +par